#include "AspectEngine.h"

namespace agtk {

/** Makes the image into a mipmapped texture, and returns the id of the texture.
	@param image The image object you wish to use.
**/
GLuint CreateTextureFromImage(Image *image) {
	GLuint textureId;
	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_2D, textureId);
	gluBuild2DMipmaps(GL_TEXTURE_2D,
					  GL_RGB,
					  image->width, image->height,
					  GL_RGB,
					  GL_UNSIGNED_BYTE,
					  image->pixels);
	return textureId;
}

/** Material constructor. **/
Material::Material() : Resource< Material >( "noname", "nopath" )
{
	diffuseColor = new Color();
	falloffColor = new Color();
	diffuseMap = NULL;
	normalMap = NULL;
	specularMap = NULL;
	glowMap = NULL;
	specularIntensity = 0.0f;
	specularPower = 0.0f;
	glowIntensity = 0.0f;
	falloffIntensity = 0.0f;
	falloffPower = 0.0f;
	falloffDetail = 0.0f;
	materialTitle = "Untitled";
	materialDescription = "No description";
	materialAuthor = "Unknown";
}

/** Material constructor. **/
Material::Material( char *name, char *path ) : Resource< Material >( name, path )
{
	int namelength = strlen(name);
	int pathlength = strlen(path);
	int totallength = namelength+pathlength+1;
	char* fullpath;
	fullpath = (char *)malloc(totallength);
	if ( fullpath != NULL )
	{
		strcpy(fullpath, path);
		strcat(fullpath, name);
	}
	Load(fullpath);
}

/** Material destructor. **/
Material::~Material()
{
	SAFE_DELETE(diffuseColor);
	SAFE_DELETE(falloffColor);
	SAFE_DELETE(diffuseMap);
	SAFE_DELETE(normalMap);
	SAFE_DELETE(specularMap);
	SAFE_DELETE(glowMap);
}

/** Load function. Called from constructor. **/
bool Material::Load(char* fullpath)
{
	TiXmlDocument doc( fullpath ); 
    bool loadOkay = doc.LoadFile();
    if ( !loadOkay ) {
		g_aspectEngine->GetLogger()->Log(LOGGER_ERROR, "Cannot open material file", fullpath);
		return false;
    }
	
	TiXmlElement* materialElement = NULL;
	TiXmlElement* propertiesElement = NULL;
	TiXmlElement* propertyElement = NULL;
	TiXmlElement* parameterElement = NULL;

	materialElement = doc.FirstChildElement("material");
    if(!materialElement) {
		g_aspectEngine->GetLogger()->Log(LOGGER_ERROR, "Cannot find <material> element in", fullpath);
		return false;
    } else {
		propertiesElement = materialElement->FirstChildElement("properties");
        if(propertiesElement) {
			// <TITLE> ELEMENT
			propertyElement = propertiesElement->FirstChildElement("title");
			if(propertyElement) {
				materialTitle=propertyElement->GetText();
			} else {
				g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <title> element in", fullpath);
				materialTitle = "Untitled";
			}
			// <DESCRIPTION> ELEMENT
			propertyElement = propertiesElement->FirstChildElement("description");
			if(propertyElement) {
				materialDescription=propertyElement->GetText();
			} else {
				g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <description> element in", fullpath);
				materialDescription = "No description";
			}
			// <AUTHOR> ELEMENT
			propertyElement = propertiesElement->FirstChildElement("author");
			if(propertyElement) {
				materialAuthor=propertyElement->GetText();
			} else {
				g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <author> element in", fullpath);
				materialAuthor = "Unknown";
			}
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <properties> element in", fullpath);
		}
		// <DIFFUSE-COLOR> ELEMENT
		parameterElement = materialElement->FirstChildElement("diffuse-color");
		if(parameterElement) {
			diffuseColor = new Color((float)atof(parameterElement->Attribute("r")), (float)atof(parameterElement->Attribute("g")), (float)atof(parameterElement->Attribute("b")), (float)atof(parameterElement->Attribute("a")));
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <diffuse-color> element in", fullpath);
			diffuseColor = new Color();
		}
		// <FALLOFF-COLOR> ELEMENT
		parameterElement = materialElement->FirstChildElement("falloff-color");
		if(parameterElement) {
			falloffColor = new Color((float)atof(parameterElement->Attribute("r")), (float)atof(parameterElement->Attribute("g")), (float)atof(parameterElement->Attribute("b")), (float)atof(parameterElement->Attribute("a")));
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <falloff-color> element in", fullpath);
			falloffColor = new Color();
		}
		// <DIFFUSE-MAP> ELEMENT
		parameterElement = materialElement->FirstChildElement("diffuse-map");
		if(parameterElement) {
			diffuseMap = new Texture(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <diffuse-map> element in", fullpath);
			diffuseMap = NULL;
		}
		// <NORMAL-MAP> ELEMENT
		parameterElement = materialElement->FirstChildElement("normal-map");
		if(parameterElement) {
			normalMap = new Texture(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <normal-map> element in", fullpath);
			normalMap = NULL;
		}
		// <SPECULAR-MAP> ELEMENT
		parameterElement = materialElement->FirstChildElement("specular-map");
		if(parameterElement) {
			specularMap = new Texture(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <specular-map> element in", fullpath);
			specularMap = NULL;
		}
		// <GLOW-MAP> ELEMENT
		parameterElement = materialElement->FirstChildElement("glow-map");
		if(parameterElement) {
			glowMap = new Texture(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <glow-map> element in", fullpath);
			glowMap = NULL;
		}
		// <SPECULAR-INTENSITY> ELEMENT
		parameterElement = materialElement->FirstChildElement("specular-intensity");
		if(parameterElement) {
			specularIntensity = (float)atof(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <specular-intensity> element in", fullpath);
			specularIntensity = 0.0f;
		}
		// <SPECULAR-POWER> ELEMENT
		parameterElement = materialElement->FirstChildElement("specular-power");
		if(parameterElement) {
			specularPower = (float)atof(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <specular-power> element in", fullpath);
			specularPower = 0.0f;
		}
		// <GLOW-INTENSITY> ELEMENT
		parameterElement = materialElement->FirstChildElement("glow-intensity");
		if(parameterElement) {
			glowIntensity = (float)atof(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <glow-intensity> element in", fullpath);
			glowIntensity = 0.0f;
		}
		// <FALLOFF-INTENSITY> ELEMENT
		parameterElement = materialElement->FirstChildElement("falloff-intensity");
		if(parameterElement) {
			falloffIntensity = (float)atof(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <falloff-intensity> element in", fullpath);
			falloffIntensity = 0.0f;
		}
		// <FALLOFF-POWER> ELEMENT
		parameterElement = materialElement->FirstChildElement("falloff-power");
		if(parameterElement) {
			falloffPower = (float)atof(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <falloff-power> element in", fullpath);
			falloffPower = 0.0f;
		}
		// <FALLOFF-DETAIL> ELEMENT
		parameterElement = materialElement->FirstChildElement("falloff-detail");
		if(parameterElement) {
			falloffDetail = (float)atof(parameterElement->GetText());
		} else {
			g_aspectEngine->GetLogger()->Log(LOGGER_WARNING, "Cannot find <falloff-detail> element in", fullpath);
			falloffDetail = 0.0f;
		}
	}
	return true;
}

void Material::UseTextures(bool yesno) {
	if (yesno)
		glEnable(GL_TEXTURE_2D);
	else
		glDisable(GL_TEXTURE_2D);
}

}